package com.ocean.product.service.impl;

import java.math.BigDecimal;
import java.net.ConnectException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.ocean.common.core.domain.entity.SysUser;
import com.ocean.common.core.page.ForeResult;
import com.ocean.common.utils.DateUtils;
import com.ocean.common.utils.DictUtils;
import com.ocean.common.utils.ShiroUtils;
import com.ocean.common.utils.StringUtils;
import com.ocean.common.utils.mail.MailUtil;
import com.ocean.common.utils.uuid.IdUtils;
import com.ocean.nc.domain.ONcFile;
import com.ocean.nc.service.IONcFileService;
import com.ocean.product.domain.ForeProduct;
import com.ocean.product.domain.OProductReport;
import com.ocean.product.service.IOProductDeptService;
import com.ocean.product.service.IOProductReportService;
import com.ocean.productCheck.domain.OProductCheckMessage;
import com.ocean.productCheck.domain.OProductCheckSms;
import com.ocean.productCheck.service.IOProductCheckMessageService;
import com.ocean.productCheck.service.IOProductCheckSmsService;
import com.ocean.productDict.domain.OForecastElement;
import com.ocean.productDict.domain.OOceanArea;
import com.ocean.productRelease.domain.OProductRelease;
import com.ocean.productRelease.service.IOProductReleaseService;
import com.ocean.system.domain.ODownLog;
import com.ocean.system.domain.OProductDept;
import com.ocean.system.domain.OProductSmsphone;
import com.ocean.system.domain.OZnwgSq;
import com.ocean.system.service.IODownLogService;
import com.ocean.system.service.IOProductSmsphoneService;
import com.sun.mail.smtp.SMTPAddressFailedException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ocean.product.mapper.OProductMapper;
import com.ocean.product.domain.OProduct;
import com.ocean.product.service.IOProductService;
import com.ocean.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.AuthenticationFailedException;

import static util.SMSSender.sendSMS;

/**
 * 产品类别Service业务层处理
 *
 * @author ocean
 * @date 2023-01-05
 */
@Service
@Slf4j
public class OProductServiceImpl implements IOProductService {

    private static final int PRT_PAGESIZE = 12;

    @Autowired
    private OProductMapper oProductMapper;
    @Autowired
    private IOProductDeptService productDeptService;
    @Autowired
    private IOProductCheckMessageService productCheckMessageService;
    @Autowired
    private IOProductReleaseService productReleaseService;
    @Autowired
    private IONcFileService ncFileService;
    @Autowired
    private IOProductReportService productReportService;
    @Autowired
    private IOProductCheckSmsService productCheckSmsService;
    @Autowired
    private IODownLogService downLogService;

    @Autowired
    private IOProductCheckSmsService checkSmsService;
    @Autowired
    private IOProductSmsphoneService oProductSmsphoneService;

    /**
     * 查询产品类别
     *
     * @param id 产品类别主键
     * @return 产品类别
     */
    @Override
    public OProduct selectOProductById(String id) {
        OProduct oProduct = oProductMapper.selectOProductById(id);
        List<OProductDept> list = productDeptService.selectOProductDeptByProductId(id);
        if (CollectionUtils.isNotEmpty(list)) {
            String[] arr = list.stream().map(OProductDept::getDeptId).collect(Collectors.toList()).toArray(new String[0]);
            String deptIds = StringUtils.join(arr, ",");
            oProduct.setDepartIds(deptIds);
        }
        return oProduct;
    }

    /**
     * 查询产品类别列表
     *
     * @param oProduct 产品类别
     * @return 产品类别
     */
    @Override
    public List<OProduct> selectOProductList(OProduct oProduct) {
        return oProductMapper.selectOProductList(oProduct);
    }

    /**
     * 新增产品类别
     *
     * @param oProduct 产品类别
     * @return 结果
     */
    @Override
    @Transactional
    public int insertOProduct(OProduct oProduct) {
        String id = IdUtils.simpleUUID();
        oProduct.setId(id);
        if (StringUtils.isEmpty(oProduct.getProductDrief())) oProduct.setProductDrief("");
        //新增产品组织中间表o_product_dept
        productDeptService.insertOProductDept(id, oProduct.getDepartIds());
        oProduct.setDepartIds(null);
        SysUser user = ShiroUtils.getSysUser();
        oProduct.setDepartId(user.getDeptId().toString());
        oProduct.setCreateName(user.getUserName());
        oProduct.setCreateBy(user.getLoginName());
        oProduct.setCreateDate(new Date());
        return oProductMapper.insertOProduct(oProduct);
    }

    /**
     * 修改产品类别
     *
     * @param oProduct 产品类别
     * @return 结果
     */
    @Override
    @Transactional
    public int updateOProduct(OProduct oProduct) {
        //修改产品组织中间表o_product_dept
        productDeptService.updateOProductDept(oProduct.getId(), oProduct.getDepartIds());
        oProduct.setDepartIds(null);
        SysUser user = ShiroUtils.getSysUser();
        oProduct.setDepartId(user.getDeptId().toString());
        oProduct.setUpdateName(user.getUserName());
        oProduct.setUpdateBy(user.getLoginName());
        oProduct.setUpdateDate(new Date());
        return oProductMapper.updateOProduct(oProduct);
    }

    /**
     * 批量删除产品类别
     *
     * @param ids 需要删除的产品类别主键
     * @return 结果
     */
    @Override
    public int deleteOProductByIds(String ids) {
        return oProductMapper.deleteOProductByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除产品类别信息
     *
     * @param id 产品类别主键
     * @return 结果
     */
    @Override
    public int deleteOProductById(String id) {
        return oProductMapper.deleteOProductById(id);
    }

    @Override
    public List<OProduct> selectFormList(OProduct oProduct) {
        return oProductMapper.selectFormList(oProduct);
    }

    /**
     * 校验nc文件是否归档
     */
    @Override
    public void checkNcFile() {
        //查找有配置校验的产品
        List<OProduct> products = oProductMapper.selectOProductsHasCheckconfig();
        for (OProduct product : products) {
            String fileName = StringUtils.EMPTY;
            //取出配置
            String checkConfig = product.getCheckConfig();
            //多个配置场合
            if (checkConfig.contains(",")) {
                String[] checkConfigArray = checkConfig.split(",");
                for (String config : checkConfigArray) {
                    fileName = analysisConfig(product.getNameRule(), config);
                    executeCheck(fileName, product, config);
                }
            }
            //单个配置场合
            else {
                fileName = analysisConfig(product.getNameRule(), checkConfig);
                executeCheck(fileName, product, checkConfig);
            }
        }
    }

    /**
     * 检验订阅文件到期时间邮件提醒订阅用户
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public void checkSubscribeTime() {

        List<Map> list = oProductMapper.checkExpireDay();
        if (list.size() < 1) {
            return;
        }
        for (int i = 0; i < list.size(); i++) {
            List<OProductSmsphone> p = oProductSmsphoneService.selectByPid((String)list.get(i).get("product_id"));//获取当前产品发送人
            long expireDay = (long)list.get(i).get("expire_day");//剩余天数
            String productName = (String) list.get(i).get("product_name");//订阅产品名
            String text = "";
            if (expireDay == 0) {
                text = "将于今日23:59到期。";
            } else {
                text = "将于" + list.get(i).get("end_date") + "日23:59分结束订阅，";
                text = "离到期日还有" + expireDay + "天。";
            }
            try {
                String fsr = "";
                for (int j = 0; j < p.size(); j++) {
                    fsr += p.get(j).getPhone()+";";
                }
                String phones = fsr.substring(0, fsr.length() - 1);
                String missionName = "测试任务";
                String groupNames = "";
                String departmentNames = "";
                String tmpPhoneNum = phones;
                String content = "您订阅的产品《" + productName + "》"+text;
                String response = sendSMS(missionName, groupNames, departmentNames, tmpPhoneNum, content);
                Map parse = (Map)JSON.parse(response);
                String code = (String)parse.get("ResultCode");
                if(code.equals("0")){
                    System.out.println("发送成功");
                    OProductCheckSms sms = new OProductCheckSms();
                    sms.setProductName(productName);//产品名称
                    sms.setProductId((String) list.get(i).get("product_id"));
                    sms.setCreateDate(new Date());//提醒日期
                    sms.setDepartId(String.valueOf((long) list.get(i).get("dept_id")));//所属部门
                    sms.setTipTypes(3);//订阅单到期提醒
                    sms.setSmsSendStatusContent(content);//提醒内容
                    int ok = checkSmsService.insertOProductCheckSms(sms);
                    System.out.println(ok);
                }
            } catch (Exception e) {
                System.out.println("发送失败"+e);
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public List<Map> checkNotUpdateProduct() {
        return oProductMapper.checkNotUpdateProduct();
    }
    public static void main(String[] args) {
        // 示例时间（支持跨月、跨年）
        String time1 = "20230203 010000";
        String time2 = "20230203 030000";

        // 自定义日期时间格式（根据输入调整）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HHmmss");
        LocalDate today = LocalDate.now();
        // 定义格式器（无需分隔符）
        DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyyMMdd");
        String f1 = today.format(f);
        LocalDateTime end1 = LocalDateTime.parse(f1+" "+"0900"+"00", formatter);
        // 解析为 LocalDateTime 对象
        LocalDateTime start = LocalDateTime.parse(time1, formatter);
        LocalDateTime end = LocalDateTime.parse(time2, formatter);

        // 计算时间差（自动处理跨月/跨年）
        Duration duration = Duration.between(start, end);
        if(duration.toHours()==6 || duration.toHours()==23 || duration.toHours()==0) {
            System.out.println(duration.toHours());
        }
        System.out.println(duration.toHours()+"错");
        // 输出示例: 时间差: 4.75 小时
    }

    /**
     * 检验产品晚传
     */
    @Override
    public void checkLateTransmission() throws Exception {
        List<OProduct> products = oProductMapper.selectwc();//获取配置晚传的产品信息
        for (int k = 0; k < products.size(); k++) {//循环配置晚传的产品信息
            if(products.get(k).getIsstop() == 1){//判断产品状态是否输入允许发送短信状态
                String[] split =  products.get(k).getWcsz().split(",");//获取配置晚传参数进行解读处理 "0_00_0900,0_07_1300".split(",");
                for (int i = 0; i < split.length; i++) {//循环当前产品每天检查的文件数
                    // 自定义日期时间格式（根据输入调整）
                    DateTimeFormatter formatter11 = DateTimeFormatter.ofPattern("yyyyMMdd HHmmss");
                    String[] split1 = split[i].split("_");
                    // 定义时间格式和目标时间（HHmm 表示 24 小时制，如 0900）
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmm");
                    LocalTime targetTime = LocalTime.parse(split1[2], formatter); // 解析为 09:00
                    // 自定义日期时间格式（根据输入调整）
                    LocalDate today = LocalDate.now();
                    DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String f1 = today.format(f);
                    LocalDateTime end1 = LocalDateTime.parse(f1+" "+split1[2]+"00", formatter11);
                    // 获取当前时间
                    LocalTime currentTime = LocalTime.now();
                    String format = currentTime.format(formatter11);
                    LocalDateTime start = LocalDateTime.parse(format, formatter);
                    if (currentTime.isAfter(targetTime)) {
                        // 计算时间差
                        Duration durationc = Duration.between(start, end1);
                        if(durationc.toHours()==6 || durationc.toHours()==24 || durationc.toHours()==0){ //超过6 24 0 小时 发短信提醒
                        //晚传设置：设置格式举例：0_18_0900 ，表示每天早9点（北京时）检查该产品起报时为前一日18时的文件。
                        // 说明：第一字段的一位数为0或1，0表示要检查的文件起报时间在检查时间的前一日，1表示为同日；中间字段的两位数为文件起报时间（小时）；
                        // 最后四位数表示在每天xx点xx分（北京时）进行检查。若有多个设置，请用英文逗号分隔。
                        System.out.println("当前时间晚于 09:00 属于晚传发短信提醒");
                        String nameRule = products.get(k).getNameRule();//获取产品名称格式

                        LocalDate today1 = LocalDate.now();  // 获取当前日期‌:ml-citation{ref="2,6" data="citationList"}
                        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");  // 定义格式‌:ml-citation{ref="2,3" data="citationList"}
                        String replaced = "";
                        if(split1[0].equals("1")){//表示当天时间，获取当天日期
                            String formattedDate = today.format(formatter1);//获取当天日期
                             replaced = nameRule.replace("YYYYMMDDHH", formattedDate+split1[1]);//替换日期时间
                            System.out.println(replaced);
                        }
                        if(split1[0].equals("0")){//表示当天时间，获取当天日期
                            // 计算前一天日期（直接减 1 天）
                            LocalDate yesterday = today.minusDays(1);
                            String string = yesterday.format(formatter1);
                             replaced = nameRule.replace("YYYYMMDDHH", string+split1[1]);//替换日期时间
                            System.out.println(replaced);
                        }
                        List<OProductRelease> oProductReleases = productReleaseService.selectByProductName(replaced);//模糊查询是否有归档文件
                        if(oProductReleases.size()<1){//如果没有归档文件证明晚传了 进行短信提醒
                            List<OProductSmsphone> p = oProductSmsphoneService.selectByPid(products.get(k).getId());//获取当前产品发送人
                            if(p.size()>0){//联系人不为空
                                String fsr = "";
                                for (int j = 0; j < p.size(); j++) {
                                    fsr += p.get(j).getPhone()+";";
                                }
                                String phones = fsr.substring(0, fsr.length() - 1);
                                String missionName = "测试任务";
                                String groupNames = "";
                                String departmentNames = "";
                                String tmpPhoneNum = phones;
                                //---------------------//计算晚传了多少时间
                              /*  currentTime.isBefore(targetTime);
                                Duration duration = Duration.between(currentTime, targetTime).abs();
                                double hoursDifference = duration.toMinutes() / 60.0;*/
                                //---------------------
                                String ts = "";
                                if(durationc.toHours() == 0){
                                    ts =   "还未归档，请尽快上传！";
                                }else if(durationc.toHours() == 6){
                                    ts =  durationc.toHours()+ "小时还未归档，请尽快上传！";
                                }else if(durationc.toHours() == 24){
                                    ts =   durationc.toHours()+ "小时还未归档，请尽快上传！";
                                }
                                String content = "《" + products.get(k).getProductName() + "》负责人您好，您的产品文件"
                                        + replaced + "超过归档检查时间" +ts;
                                String response = sendSMS(missionName, groupNames, departmentNames, tmpPhoneNum, content);
                                Map parse = (Map)JSON.parse(response);
                                String code = (String)parse.get("ResultCode");
                                if(code.equals("0")){
                                    System.out.println("发送成功");
                                    OProductCheckSms sms = new OProductCheckSms();
                                    sms.setProductName(products.get(k).getProductName());//产品名称
                                    sms.setProductId(products.get(k).getId());
                                    sms.setCreateDate(new Date());//提醒日期
                                    sms.setDepartId(products.get(k).getDepartId());//所属部门
                                    sms.setTipTypes(1);//晚传提醒
                                    sms.setSmsSendStatusContent(content);//提醒内容
                                    int ok = checkSmsService.insertOProductCheckSms(sms);
                                    System.out.println(ok);
                                }
                            }
                        }
                    }
                }
            }
            }
        }

 /*       List<OProductReport> productReportList = productReportService.getLessThanLateTransmissionList();
        if (productReportList.size() > 0) {
            for (int i = 0; i < productReportList.size(); i++) {
                String fileName = productReportList.get(i).getFileName();
                List<OProductRelease> productReleases = productReleaseService.selectByProductName(fileName);
                if (productReleases.size() > 0) {
                    OProductReport productReport = productReportList.get(i);
                    productReport.setStatus(2);
                    // 采用产品最后发布的日期
                    productReport.setUpdateDate(productReleases.get(0).getReleaseDate());
                    productReportService.updateOProductReport(productReport);
                }
            }
        }
        //晚传短信、邮件提示
        List<OProductReport> productReportList1 = productReportService.getEqualLateTransmissionList();
        if (productReportList1.size() > 0) {
            for (OProductReport productReport : productReportList1) {
                String fileName = productReport.getFileName();
                List<OProductRelease> productReleases = productReleaseService.selectByProductName(fileName);
                if (productReleases.size() == 0) {
                    OProduct product = oProductMapper.selectOProductById(productReport.getProductId());
                    if (product != null) {
                        //是否发送短信
                        if (null != product.getSmsTipPhone() && !("").equals(product.getSmsTipPhone())) {
                            OProductCheckSms opcs = new OProductCheckSms();
                            opcs.setTipTypes(0);
                            opcs.setFileName(fileName);
                            List<OProductCheckSms> productCheckSms = productCheckSmsService.selectOProductCheckSmsList(opcs);
                            if (productCheckSms.size() > 0) {
                                String phones = product.getSmsTipPhone();
                                // SMS_168585972
                                String templateCode = DictUtils.getDictLabel2("params", "templateCode_late", "SMS_168585972");
                                String templateParam = "{\"productname\":\"" + product.getProductName() + "\",\"filename\":\"" + fileName + "\",\"Limit\":\"" + product.getLateTransmission() / 60 + "小时\"}";
                                boolean flag = false;
                                boolean result = false;
                                //多个电话配置
                                if (phones.contains(",")) {
                                    String[] phoneNumbers = phones.split(",");
                                    for (String phoneNumber : phoneNumbers) {
                                        result = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phoneNumber, getSignName(), templateCode, templateParam);
                                        if (result) {
                                            flag = true;
                                        }
                                    }
                                } else {
                                    flag = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phones, getSignName(), templateCode, templateParam);
                                }
                                OProductCheckSms productCheckSmsEntity = productCheckSms.get(0);
                                productCheckSmsEntity.setUpdateDate(new Date());
                                productCheckSmsEntity.setTipTypes(1);
                                productCheckSmsEntity.setSmsSendStatusContent(flag == true ? productCheckSmsEntity.getSmsSendStatusContent() + ",晚传提醒发送成功" : productCheckSmsEntity.getSmsSendStatusContent() + ",晚传提醒发送失败");
                                productCheckSmsService.updateOProductCheckSms(productCheckSmsEntity);
                            }
                        }
                        if (null != product.getSendMail() && !("").equals(product.getSendMail())) {
                            OProductCheckMessage opcm = new OProductCheckMessage();
                            opcm.setDeleted(0);
                            opcm.setTipTypes(0);
                            opcm.setFileName(fileName);
                            List<OProductCheckMessage> productCheckMessages = productCheckMessageService.getList(opcm);
//                            List<ProductCheckMessageEntity> productCheckMessages = this.findHql("from ProductCheckMessageEntity productCheckMessage "
//                                    + "where productCheckMessage.deleted = 0 AND productCheckMessage.tipTypes = 0 AND productCheckMessage.fileName = ?", fileName);
                            if (productCheckMessages.size() > 0) {

                                int lateTime = product.getLateTransmission();
                                double normalRate = new BigDecimal((float) lateTime / 60).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                                new Double(normalRate).intValue();
                                OProductCheckMessage productCheckMessage = productCheckMessages.get(0);
                                productCheckMessage.setTipTypes(1);
                                productCheckMessageService.updateOProductCheckMessage(productCheckMessage);
                                String content = "【国家海洋预报云服务平台】 《" + product.getProductName() + "》负责人您好，您的产品文件"
                                        + fileName + "超过归档检查时间" + new Double(normalRate).intValue() + "小时还未归档，请尽快上传！";
                                ncFileService.sendMail(content, product.getSendMail());
                            }
                        }
                    }
                }
            }
        }*/
    }

    /**
     * 检验产品补传
     */
    @Override
    public void checkRepairTransmission() {
        List<OProductReport> productReportList = productReportService.getNeedTransmissionList();
//        String sql = "SELECT pr.* FROM o_product_report pr LEFT JOIN o_product p ON pr.product_id = p.id "
//                + "WHERE pr.status = 0 AND TO_DAYS(SYSDATE()) -  TO_DAYS(pr.create_date) <= p.repair_transmission "
//                + "AND TIMESTAMPDIFF(MINUTE,pr.create_date,SYSDATE()) >= p.late_transmission "
//                + "AND TIMESTAMPDIFF(HOUR,pr.create_date,SYSDATE()) < (24 * p.repair_transmission)";
        if (productReportList.size() > 0) {
            for (OProductReport productReport : productReportList) {
                String fileName = productReport.getFileName();
                List<OProductRelease> productReleases = productReleaseService.selectByProductName(fileName);
                if (productReleases.size() > 0) {
                    productReport.setStatus(3);
                    // 采用产品最后发布的日期
                    productReport.setUpdateDate(productReleases.get(0).getReleaseDate());
                    productReportService.updateOProductReport(productReport);
                }
            }
        }
        //补传短信、邮件提示uru
        List<OProductReport> productReports = productReportService.getNeedSendsmsList();
//        String sql1 = "SELECT pr.* FROM o_product_report pr LEFT JOIN o_product p ON pr.product_id = p.id "
//                + "WHERE pr.status = 0 AND TO_DAYS(SYSDATE()) -  TO_DAYS(pr.create_date) <= p.repair_transmission "//天数<=补传
//                + "AND TIMESTAMPDIFF(MINUTE,pr.create_date,SYSDATE()) >= p.late_transmission "//>=晚传
//                + "AND TIMESTAMPDIFF(HOUR,pr.create_date,SYSDATE()) < (24 * p.repair_transmission) "//h<补传
//                + "AND TO_DAYS(SYSDATE()) - TO_DAYS(pr.create_date) = p.repair_tip_sms_day "//为短信提醒日
//                + "AND TIMESTAMPDIFF(HOUR,pr.create_date,SYSDATE()) >= (24 * p.repair_tip_sms_day)";//h>=短信提醒日
        //判断是否有漏传文件
        if (productReports.size() > 0) {
            for (OProductReport productReport : productReports) {
                String fileName = productReport.getFileName(); //文件名
                //查询是否已经上传归档
                List<OProductRelease> productReleases = productReleaseService.selectByProductName(fileName);
                //还未未归档时
                if (productReleases.size() == 0) {
                    //通过产品id获取产品信息
                    OProduct product = oProductMapper.selectOProductById(productReport.getProductId());
                    //电话不为空时
                    if (product != null && null != product.getSmsTipPhone() && !("").equals(product.getSmsTipPhone())) {
                        //查询是否发过短信，并且已经发送过晚传通知
                        OProductCheckSms opcs = new OProductCheckSms();
                        opcs.setTipTypes(1);
                        opcs.setFileName(fileName);
                        List<OProductCheckSms> productCheckSmsList = productCheckSmsService.selectOProductCheckSmsList(opcs);
                        //发送过晚传提醒时
                        if (productCheckSmsList.size() > 0) {
                            String phones = product.getSmsTipPhone();
                            // SMS_168585979
                            String templateCode = DictUtils.getDictLabel2("params", "templateCode_repair", "SMS_168585979");
                            String templateParam = "{\"productname\":\"" + product.getProductName() + "\",\"filename\":\"" + fileName + "\",\"DLtime\":\"" + product.getRepairTipSmsDay() + "天\"}";
                            boolean flag = false;
                            boolean result = false;
                            //多个电话配置
                            if (phones.contains(",")) {
                                String[] phoneNumbers = phones.split(",");
                                for (String phoneNumber : phoneNumbers) {
                                    result = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phoneNumber, getSignName(), templateCode, templateParam);
                                    if (result) {
                                        flag = true;
                                    }
                                }
                            } else {
                                flag = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phones, getSignName(), templateCode, templateParam);
                            }
                            OProductCheckSms productCheckSms = productCheckSmsList.get(0);
                            productCheckSms.setUpdateDate(new Date());
                            productCheckSms.setTipTypes(2);
                            productCheckSms.setSmsSendStatusContent(flag == true ? productCheckSms.getSmsSendStatusContent() + ",补传提醒发送成功" : productCheckSms.getSmsSendStatusContent() + ",补传提醒发送失败");
                            productCheckSmsService.updateOProductCheckSms(productCheckSms);
                        }
                    }
                    if (null != product.getSendMail() && !("").equals(product.getSendMail())) {
                        OProductCheckMessage opcm = new OProductCheckMessage();
                        opcm.setDeleted(0);
                        opcm.setTipTypes(1);
                        opcm.setFileName(fileName);
                        List<OProductCheckMessage> productCheckMessages = productCheckMessageService.getList(opcm);
//                        List<ProductCheckMessageEntity> productCheckMessages = this.findHql("from ProductCheckMessageEntity productCheckMessage "
//                                + "where productCheckMessage.deleted = 0 AND productCheckMessage.tipTypes = 1 AND productCheckMessage.fileName = ?", fileName);
                        if (productCheckMessages.size() > 0) {
                            OProductCheckMessage productCheckMessage = productCheckMessages.get(0);
                            productCheckMessage.setTipTypes(2);
                            productCheckMessageService.updateOProductCheckMessage(productCheckMessage);
                            String content = "【国家海洋预报云服务平台】 《" + product.getProductName() + "》上传负责人您好，您的产品文件"
                                    + fileName + "经过" + product.getRepairTipSmsDay() + "天仍未上传平台，请尽快上传以免导致文件状态变为漏传！";
                            ncFileService.sendMail(content, product.getSendMail());
                        }
                    }
                }
            }
        }
    }

    @Override
    public Map<String, List<String>> selectTypeAndDeptIsOpen() {
        List<Map<String, String>> list = oProductMapper.selectTypeAndDeptIsOpen();
        //{"在分析产品"：["区域1"，"区域2"]}
        Map<String, List<String>> result = new HashMap<>();
        for (Map<String, String> map : list) {
            String type = map.get("type");
            if (result.containsKey(type)){
                String name = map.get("name");
                if (!result.get(type).contains(name))
                    result.get(type).add(map.get("name"));
            }else {
                List<String> data = new ArrayList<>();
                data.add(map.get("name"));
                result.put(type,data);
            }
        }
//        Map<String, List<String>> result = list.stream()
//                .collect(Collectors.groupingBy(m -> m.get("type"), Collectors.mapping(m -> m.get("name"), Collectors.toList())));

        return result;
    }
/*
    public List<Map<String, Object>> selectTypeAndDeptIsOpen() {
        List<Map<String, String>> list = oProductMapper.selectTypeAndDeptIsOpen();
        //[{'type':'kk','name':[{'pname':'1','children':[]},{'pname':'3','children':[]}]}]
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> t = new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, String> m = list.get(i);
            if (!t.containsKey(m.get("type"))) {
                t.put("type", m.get("type"));
                t.put(m.get("type"), result.size());
                Map<String, Object> map = new HashMap<>();
                map.put("type", m.get("type"));
                List<String> name = new ArrayList<>();
                name.add(m.get("name"));
                map.put("name", name);
                result.add(map);
            } else {
                Map<String, Object> map = result.get((Integer) t.get(m.get("type")));
                List<String> tmp = castList(map.get("name"), String.class);
                if (!tmp.contains(m.get("name")))
                    tmp.add(m.get("name"));
                map.put("name", tmp);
            }
        }
        for (Map<String, Object> map : result) {
            List<Map<String, Object>> v = new ArrayList<>();
            List<String> tmp = castList(map.get("name"), String.class);
            for (String s : tmp) {
                Map<String, Object> m = new HashMap<>();
                m.put("pname",s);m.put("children",new ArrayList<>());
                v.add(m);
            }
            map.put("name",v);
        }
        return result;
    }
*/

    @Override
    public Map<String, Map<String, List<String>>> selectTypeAndDeptIsOpenLoggedIn() {
        SysUser sysUser = ShiroUtils.getSysUser();
        List<Map<String, String>> list = oProductMapper.selectTypeAndDeptIsOpenLoggedIn(sysUser.getDeptId());
        //{"在分析产品"：{"区域1":[]，"区域2":["资料1","资料2"]}}
        Map<String, Map<String,List<String>>> result = new HashMap<>();
        for (Map<String, String> map : list) {
            String type = map.get("type");
            //存在该类型
            if (result.containsKey(type)){
                String name = map.get("name");
                Map<String,List<String>> areas = result.get(type);
                //存在该区域
                if (areas.containsKey(name)) {
                    areas.get(name).add(map.get("pname"));
                }else {
                    List<String> data = new ArrayList<>();
                    data.add(map.get("pname"));
                    areas.put(name,data);
                }
            }else {
                List<String> data = new ArrayList<>();
                data.add(map.get("pname"));
                Map<String, List<String>> area = new HashMap<>();
                area.put(map.get("name"),data);
                result.put(type,area);
            }
        }
        return result;
    }

    @Override
    public ForeResult getProduct(String productType, String depart, String oceanArea, String element, String mode, int currentPage) {
        SysUser sysUser = ShiroUtils.getSysUser();
        Long deptId = sysUser.getDeptId();
        ForeResult foreResult = new ForeResult();
        if (deptId == null) {
            return foreResult;
        }
        int pageSize = PRT_PAGESIZE;
        int start = (currentPage - 1) * pageSize;
        int countAll = oProductMapper.selectCountSql(productType,depart,oceanArea,element,mode,deptId);
        List<Map> list = oProductMapper.productSql(productType,depart,oceanArea,element,mode,deptId,start,pageSize);
        if (list.size() == 0) {
            foreResult.setResult("fail");
            foreResult.setTotalData(0);
            foreResult.setCurrentPage(1);
            foreResult.setPageCount(1);
        }
        else {
            foreResult.setResult("success");
            foreResult.setTotalData(list.size());
            List<Object> products = new ArrayList<Object>();
            for (int i = 0; i < list.size(); i++) {
                OProduct productEntity = (OProduct) JSONObject.toJavaObject(new JSONObject(list.get(i)), OProduct.class);
                OOceanArea oceanarea = (OOceanArea) JSONObject.toJavaObject(new JSONObject(list.get(i)), OOceanArea.class);
                OForecastElement forecastElement = (OForecastElement) JSONObject.toJavaObject(new JSONObject(list.get(i)), OForecastElement.class);
//                OProduct productEntity = new OProduct();//(OProduct) list.get(i)[0];
                ForeProduct foreProduct = new ForeProduct();
//                foreProduct.setArea(((OOceanArea) list.get(i)[1]).getAreaName());
//                foreProduct.setElement(((OForecastElement) list.get(i)[2]).getElementName());
                foreProduct.setArea(oceanarea.getAreaName());
                foreProduct.setElement(forecastElement.getElementName());
                foreProduct.setProductId(productEntity.getId());
                foreProduct.setAging(productEntity.getForecastAging());
                foreProduct.setResolution(productEntity.getResolution());
                foreProduct.setFrequency(productEntity.getFrequency());
                foreProduct.setFileType(productEntity.getFileType());
                foreProduct.setProductName(productEntity.getProductName());
                foreProduct.setIsPreview(productEntity.getIsPreview()); // 设置为可以预览
                products.add(foreProduct);
            }
            foreResult.setDatas(products);
            foreResult.setCurrentPage(currentPage);
            int pageCount = countAll % pageSize == 0 ? countAll / pageSize : countAll / pageSize + 1;
            foreResult.setPageCount(pageCount);
            foreResult.setPageSize(pageSize);
        }
        return foreResult;
    }

    @Override
    public String downLoad(String fileId) {
        // 下载记录加1
        ONcFile ncFile = ncFileService.selectONcFileById(fileId);
        OProductRelease pr = new OProductRelease();pr.setNcFileId(ncFile.getId());
        List<OProductRelease> productReleases = productReleaseService.selectOProductReleaseList(pr);
        OProductRelease productRelease = new OProductRelease();
        if (CollectionUtils.isNotEmpty(productReleases))
            productRelease = productReleases.get(0);
        ODownLog downLog = new ODownLog();
        downLog.setDownTime(new Date());
        downLog.setProductId(productRelease.getProductId());
        SysUser user = ShiroUtils.getSysUser();
        if (user != null) {
            downLog.setUserId(user.getUserId().toString());
        } else {
            downLog.setUserId("");
        }
        downLogService.insertODownLog(downLog);
        // path是指欲下载的文件的路径。
        String path = ncFile.getFilePath() + "/" + ncFile.getFileName();
        return path;
    }

    @Override
    public List<OProduct> isjc(String pname) {
        return oProductMapper.isjc(pname);
    }

    @Override
    public List<OProduct> getnamegz(String pname) {
        return oProductMapper.getnamegz(pname);
    }

    @Override
    public List<OProduct> selectFormListsms(OProduct oProduct) {
        return oProductMapper.selectFormListsms(oProduct);
    }

    @Override
    public List<OZnwgSq> selectFormListsmsznwg(OZnwgSq oZnwgSq) {
        return oProductMapper.selectFormListsmsznwg(oZnwgSq);
    }

    @Override
    public List<OZnwgSq> selectFormListznwg() {
        return oProductMapper.selectFormListznwg();
    }

    public static <T> List<T> castList(Object obj, Class<T> clazz) {
        List<T> result = new ArrayList<T>();
        if (obj instanceof List<?>) {
            for (Object o : (List<?>) obj) {
                result.add(clazz.cast(o));
            }
            return result;
        }
        return null;
    }

    /**
     * 执行提醒操作
     *
     * @param fileName
     * @param product
     */
    private void executeCheck(String fileName, OProduct product, String checkConfig) {
        log.info("提醒未归档的文件名：" + fileName);
        if (StringUtils.isNotEmpty(fileName)) {
            //是否已经提醒 如果已提醒则不在提醒
            OProductCheckMessage pcm = new OProductCheckMessage();
            pcm.setDeleted(0);
            pcm.setFileName(fileName);
            List<OProductCheckMessage> productCheckMessages = productCheckMessageService.getList(pcm);
            //未提醒场合
            if (productCheckMessages.size() == 0) {//productCheckMessages==0 说明未提醒
                //查找归档记录
                List<OProductRelease> productReleases = productReleaseService.selectByProductName(fileName);//查看是否有归档记录
                //创建报表对象
                OProductReport productReport = new OProductReport();
                productReport.setProductId(product.getId());
                productReport.setProductName(product.getProductName());
                productReport.setFileName(fileName);
                productReport.setCreateDate(new Date());
                //未归档场合
                if (productReleases.size() == 0) {//没有归档记录，插入提醒表
                    //插入消息表
                    OProductCheckMessage productCheckMessage = new OProductCheckMessage();
                    productCheckMessage.setId(IdUtils.simpleUUID());
                    //时间
                    productCheckMessage.setCreateDate(DateUtils.getNowDate());
                    //文件名
                    productCheckMessage.setFileName(fileName);
                    //组织ID
                    productCheckMessage.setDepartId(product.getDepartId());
                    //产品类别ID
                    productCheckMessage.setProductId(product.getId());
                    //是否删除
                    productCheckMessage.setDeleted(0);
                    //邮件提醒类型
                    productCheckMessage.setTipTypes(0);
                    if (checkConfig(checkConfig)) {
                        productCheckMessageService.save(productCheckMessage);
                        //发送邮件提醒(根据每个产品设定的时间进行归档提醒)
                        //ncFileService.sendMail("【国家海洋预报云服务平台】" + "《" + product.getProductName() + "》负责人您好，您的产品文件" + fileName + "在其归档检查时间还未在平台归档，请及时检查问题并尽快上传数据！", product.getSendMail());
                        //漏传(异常)
                        productReport.setStatus(0);
                        productReport.setBz("没有归档记录(异常)");
                        OProductReport opr = new OProductReport();
                        opr.setStatus(0);
                        opr.setFileName(fileName);
                        List<OProductReport> productReports = productReportService.selectOProductReportList(opr);
                        if (productReports.size() == 0) {
                            productReportService.save(productReport);
                        }
                        //是否发送短信
                        if (null != product.getSmsTipPhone() && !("").equals(product.getSmsTipPhone())) {
                            String phones = product.getSmsTipPhone();
                            // SMS_168590984
                            String templateCode = getTemplateCodeTimeout();
                            String templateParam = "{\"productname\":\"" + product.getProductName() + "\",\"filename\":\"" + fileName + "\"}";
                            boolean flag = false;
                            boolean result = false;
                            // 多个电话配置
                            if (phones.contains(",")) {
                                String[] phoneNumbers = phones.split(",");
                                for (String phoneNumber : phoneNumbers) {
                                    result = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phoneNumber, getSignName(), templateCode, templateParam);
                                    //多条发送有一条成功就视为成功
                                    if (result) {
                                        flag = true;
                                    }
                                }
                            } else {
                                flag = SendSms(getAccessKeyId(), getAccessSecret(), getRegionid(), phones, getSignName(), templateCode, templateParam);
                            }
                            OProductCheckSms productCheckSms = new OProductCheckSms();
                            productCheckSms.setProductId(product.getId());
                            productCheckSms.setFileName(fileName);
                            productCheckSms.setDepartId(product.getDepartId());
                            productCheckSms.setCreateDate(new Date());
                            productCheckSms.setTipTypes(0);
                            productCheckSms.setSmsSendStatusContent(flag == true ? "异常提醒发送成功" : "异常提醒发送失败");
                            productCheckSmsService.insertOProductCheckSms(productCheckSms);
                        }
                    } else {
                        return;
                    }
                } else {
                    //正常上传(已归档)
                    productReport.setStatus(1);
                    productReport.setBz("正常上传(已归档)");
                    OProductReport opr = new OProductReport();
                    opr.setStatus(1);
                    opr.setFileName(fileName);
                    List<OProductReport> productReports = productReportService.selectOProductReportList(opr);
                    if (productReports.size() > 0) {
                        return;
                    } else {
                        productReportService.save(productReport);
                    }
                }
            }
        }
    }

    /**
     * 获取短信归档超时提示模板Code
     */
    public String getTemplateCodeTimeout() {
        return DictUtils.getDictLabel2("params", "templateCode_timeout", "SMS_168590984");
    }

    /**
     * 获取短信AccessKeyId
     */
    public String getAccessKeyId() {
        return DictUtils.getDictLabel2("params", "accessKeyId", "LTAIqcYijk60jZcz");
    }

    /**
     * 获取短信AccessSecret
     */
    public String getAccessSecret() {
        return DictUtils.getDictLabel2("params", "accessSecret", "pt3jHb1tTwPvK0uh42VQIwjLASu3h6");
    }

    /**
     * 获取短信Regionid
     */
    public String getRegionid() {
        return DictUtils.getDictLabel2("params", "regionid", "cn-hangzhou");
    }

    /**
     * 获取短信SignName
     */
    public String getSignName() {
        return DictUtils.getDictLabel2("params", "signName", "国家海洋预报云服务平台");
    }

    /**
     * 短信发送
     *
     * @param accessKeyId
     * @param accessSecret
     * @param regionid
     * @param phoneNumbers
     * @param signName
     * @param templateCode
     * @param templateParam
     * @return
     */
    public boolean SendSms(String accessKeyId, String accessSecret, String regionid, String phoneNumbers, String signName, String templateCode, String templateParam) {
        DefaultProfile profile = DefaultProfile.getProfile(regionid, accessKeyId, accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");
        request.putQueryParameter("RegionId", regionid);
        request.putQueryParameter("PhoneNumbers", phoneNumbers);
        request.putQueryParameter("SignName", signName);
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", templateParam);
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            System.out.println(e.getMessage());
//            this.addAutoLog("短信发送失败,失败原因：" + e.getMessage(), Globals.Log_Type_OTHER, Globals.Log_Leavel_ERROR);
            return false;
        } catch (ClientException e) {
//            this.addAutoLog("短信发送失败,失败原因：" + e.getMessage(), Globals.Log_Type_OTHER, Globals.Log_Leavel_ERROR);
            System.out.println(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 解析规则
     *
     * @param checkConfig 配置的校验规则
     * @return 返回需要校验的文件名
     */
    private static String analysisConfig(String nameRule, String checkConfig) {
        log.info("定时规则为：" + checkConfig);
        try {
            //获取当前时间
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);
            int month = now.get(Calendar.MONTH) + 1;
            int day = now.get(Calendar.DAY_OF_MONTH);
            String fileName = StringUtils.EMPTY;
            String[] checkConfigArray = checkConfig.split("_");
            SimpleDateFormat s = new SimpleDateFormat("HHmm");
            String curDate = s.format(now.getTime());
            //比较时间是否达到校验时间
            if (Integer.parseInt(checkConfigArray[2]) <= Integer.parseInt(curDate)) {//判断当前时间是否大于配置中的HHmm时间
                //第一个参数 0,1 0校验前一天的 1校验当天的
                if ("0".equals(checkConfigArray[0])) {
                    //回滚一天
                    Date today = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
                    String yesterday = simpleDateFormat.format(today) + checkConfigArray[1];
                    fileName = nameRule.replaceAll("YYYYMMDDHH", yesterday);
                    return fileName;
                } else {
                    String monthStr = "";
                    String dayStr = "";
                    monthStr = month < 10 ? "0" + month : String.valueOf(month);
                    dayStr = day < 10 ? "0" + day : String.valueOf(day);
                    String ymd = year + monthStr + dayStr + checkConfigArray[1];
                    //替换掉名称
                    fileName = nameRule.replaceAll("YYYYMMDDHH", ymd);
                    return fileName;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return StringUtils.EMPTY;
    }

    /**
     * 解析规则
     *
     * @param checkConfig 配置的校验规则
     * @return 返回需要校验的文件名
     */
    private static boolean checkConfig(String checkConfig) {
        log.info("定时规则为：" + checkConfig);
        if (StringUtils.isBlank(checkConfig)) {
            return true;
        }
        if (checkConfig.contains(",")) {
            String[] checkConfigArray = checkConfig.split(",");
            for (String config : checkConfigArray) {
                try {
                    //获取当前时间
                    Calendar now = Calendar.getInstance();
                    SimpleDateFormat s = new SimpleDateFormat("HHmm");
                    String curDate = s.format(now.getTime());
                    String[] checkConfi = config.split("_");
                    //比较时间是否达到校验时间
                    if (Integer.parseInt(checkConfi[2]) == Integer.parseInt(curDate)) {
                        return true;
                    } else {
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //单个配置场合
        else {
            try {
                //获取当前时间
                Calendar now = Calendar.getInstance();
                SimpleDateFormat s = new SimpleDateFormat("HHmm");
                String curDate = s.format(now.getTime());
                String[] checkConfigArray = checkConfig.split("_");
                //比较时间是否达到校验时间
                if (Integer.parseInt(checkConfigArray[2]) == Integer.parseInt(curDate)) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }

}
